pub(crate) mod define;
mod os;
pub mod usb;



#[cfg(test)]
mod tests {
    use std::time::{Duration, Instant};
    use futures::{StreamExt};
    use log::{info, LevelFilter};
    use tokio::select;
    use crate::define::{UsbControlRecipient, UsbControlTransferType};
    use super::*;
    fn init() {
        let _ = env_logger::builder().filter_level(LevelFilter::Debug).is_test(true).try_init();
    }

    #[tokio::test]
    async fn all() {
        init();

        let manager = usb::UsbManager::new();
        let list = manager.device_all().await.unwrap();

        for device in list {
            info!("{:?}", device);
        }

        info!("finish");
    }


    #[tokio::test]
    async fn find() {
        init();

        let manager = usb::UsbManager::new();
        let list = manager.device_find(Some(0x1D50), None).await.unwrap();

        for device in list {
            info!("{:?}", device);
        }

        info!("finish");
    }


    #[tokio::test]
    async fn open() {
        init();

        let manager = usb::UsbManager::new();
        let list = manager.device_find(Some(0x1D50), Some(0x6089)).await.unwrap();

        for mut device in list {
            device.open().await.unwrap();
            info!("opened");
            let mut request = define::ControlTransferRequest::default();
            request.request_type.recipient=UsbControlRecipient::Device;
            request.request_type.control_transfer_type=UsbControlTransferType::Vendor;
            request.request=1;
            request.value=1;


            device.control_transfer_out(request).await.unwrap();


        }

        info!("finish");
    }
    #[tokio::test]
    async fn read() {
        init();

        let manager = usb::UsbManager::new();
        let list = manager.device_find(Some(0x1D50), Some(0x6089)).await.unwrap();

        for mut device in list {
            device.open().await.unwrap();
            info!("opened");
            let mut request = define::ControlTransferRequest::default();
            request.request_type.recipient=UsbControlRecipient::Device;
            request.request_type.control_transfer_type=UsbControlTransferType::Vendor;
            request.request=15;
            request.len =30;

            let data = device.control_transfer_in(request).await.unwrap();


            let version = String::from_utf8(data).unwrap();

            info!("version: {}", version);

        }

        info!("finish");
    }


    // #[tokio::test]
    // async fn read2() {
    //     init();
    //
    //     let manager = usb::UsbManager::new();
    //     let list = manager.device_find(Some(0x1D50), Some(0x6089)).await.unwrap();
    //
    //     for mut device in list {
    //         device.open().await.unwrap();
    //         info!("opened");
    //         device.test().await.unwrap();
    //
    //
    //     }
    //
    //     info!("finish");
    // }


    // #[tokio::test]
    // async fn bulk_read() {
    //     init();
    //
    //     let manager = usb::UsbManager::new();
    //     let list = manager.device_find(Some(0x1D50), Some(0x6089)).await.unwrap();
    //
    //     for mut device in list {
    //         device.open().await.unwrap();
    //         info!("opened");
    //
    //         let interface = device.default_interface().unwrap();
    //         let mut pip = interface.get_bulk_in_pipes().unwrap().remove(0);
    //         let mut buf = vec![0; 1024];
    //
    //         for i in 0..5 {
    //             let n = pip.read(&mut buf).await.unwrap();
    //             info!("rcv: {}", n)
    //         }
    //
    //     }
    //
    //     info!("finish");
    // }

    #[tokio::test]
    async fn bulk_read2() {
        init();

        let manager = usb::UsbManager::new();
        let mut list = manager.device_find(Some(0x1D50), Some(0x6089)).await.unwrap();
        let mut device = list.remove(0);
        device.open().await.unwrap();
        info!("opened");
        let interface = device.default_interface().unwrap();
        let mut rx = interface.open_bulk_in_channel(262144, 1).unwrap();
        let (stop_tx, mut stop_rx)  = tokio::sync::oneshot::channel();


        tokio::spawn(async move{
            let mut all = 0usize;
            let start = Instant::now();
            loop{
                select! {
                    res = rx.next() => {
                        match res{
                            Some(data)=> {
                                 all += data.len();
                            }
                            None=>break,
                        }
                    }
                    _ = (&mut stop_rx) => {
                        break;
                    }
                }
            }
            let duration = Instant::now().duration_since(start);
            let bits = (all) as f64;
            let seconds = duration.as_secs_f64();
            let mb = (bits / seconds) / 1_000_000.0;

            info!("速度：{}", mb);
            info!("接收停止");
        });


        tokio::time::sleep(Duration::from_secs(5)).await;
        info!("send stop");
        stop_tx.send(1).unwrap();
        tokio::time::sleep(Duration::from_secs(1)).await;
        info!("finish");
    }
}
